{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h1 align = 'center'> 学会看见 </h1>\n",
    "\n",
    "<h2 align = 'center'> 第9部分：偏差方差对决 </h2>\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 导入数据和支持函数\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Populating the interactive namespace from numpy and matplotlib\n"
     ]
    }
   ],
   "source": [
    "# 引入 %pylab inline 用于在Jupyter Notebook中显示图形，并导入相关库\n",
    "%pylab inline\n",
    "\n",
    "# 从 supportFunctions 模块中导入所有函数和类\n",
    "from supportFunctions import *\n",
    "\n",
    "# 导入 pickle 库，cPickle 在 Python 3 中被合并到 pickle\n",
    "import pickle\n",
    "\n",
    "# 指定 pickle 文件的文件名\n",
    "pickleFileName = 'data/fingerDataSet' + '.pickle'\n",
    "\n",
    "# 以二进制只读模式打开 pickle 文件\n",
    "with open(pickleFileName, 'rb') as pickleFile:\n",
    "    # 从 pickle 文件中加载数据并存储到变量 data 中\n",
    "    data = pickle.load(pickleFile, encoding='latin1')\n",
    "\n",
    "# 不再需要手动关闭 pickle 文件，使用 with 语句会在离开其代码块时自动关闭文件"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true,
    "jupyter": {
     "outputs_hidden": true
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# 重新设置训练数据，仅使用三个图像：\n",
    "trainingExampleIndices = [7, 30, 46]\n",
    "\n",
    "# 从数据中选择指定索引的训练样本\n",
    "trainingExamples = [data[index] for index in trainingExampleIndices]\n",
    "\n",
    "# 从训练样本中提取特征和标签，使用 'image1bit' 并设置 dist 为 4\n",
    "trainX, trainY = extractExamplesFromList(trainingExamples, whichImage='image1bit', dist=4)\n",
    "\n",
    "# 选择两个图像用于测试：\n",
    "testingExampleIndices = [40, 41]\n",
    "\n",
    "# 从数据中选择指定索引的测试样本\n",
    "testingExamples = [data[index] for index in testingExampleIndices]\n",
    "\n",
    "# 从测试样本中提取特征和标签，使用 'image1bit' 并设置 dist 为 4\n",
    "testX, testY = extractExamplesFromList(testingExamples, whichImage='image1bit', dist=4)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 搜索1像素规则\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Time elapsed = 0.007 seconds.\n"
     ]
    }
   ],
   "source": [
    "# 初始化空列表用于存储规则和错误数\n",
    "rules = []\n",
    "numErrors = []\n",
    "\n",
    "# 记录开始时间\n",
    "startTime = time.time()\n",
    "\n",
    "# 遍历81个特征\n",
    "for i in range(81):\n",
    "    # 构建规则：如果 trainX 中的第 i 列等于 0，则为 True\n",
    "    yHat = (trainX[:, i] == 0)\n",
    "    \n",
    "    # 计算错误数并添加到 numErrors 列表\n",
    "    numErrors.append(sum(abs(yHat - trainY)))\n",
    "    \n",
    "    # 添加规则到 rules 列表\n",
    "    rules.append([i, 0])\n",
    "\n",
    "    # 构建规则：如果 trainX 中的第 i 列等于 1，则为 True\n",
    "    yHat = (trainX[:, i] == 1)\n",
    "    \n",
    "    # 计算错误数并添加到 numErrors 列表\n",
    "    numErrors.append(sum(abs(yHat - trainY)))\n",
    "    \n",
    "    # 添加规则到 rules 列表\n",
    "    rules.append([i, 1])\n",
    "\n",
    "# 计算总共耗时\n",
    "timeElapsed = time.time() - startTime\n",
    "\n",
    "# 打印耗时信息\n",
    "print('Time elapsed = ' + str(round(timeElapsed, 3)) + ' seconds.')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "81"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 找到错误数最小的规则的索引\n",
    "np.argmin(np.array(numErrors))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "规则编号81获胜！\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 可视化规则\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": true,
    "jupyter": {
     "outputs_hidden": true
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# 导入 matplotlib.colors 模块\n",
    "import matplotlib.colors as mcolors\n",
    "\n",
    "# 定义颜色转换器\n",
    "c = mcolors.ColorConverter().to_rgb\n",
    "\n",
    "# 创建蓝色 colormap\n",
    "bw = make_colormap([(1,1,1), (1,1,1), 0.33, c('blue'), c('blue'), 0.66, c('blue')])\n",
    "\n",
    "# 创建红色 colormap\n",
    "rw = make_colormap([(1,1,1), (1,1,1), 0.33, c('red'), c('red'), 0.66, c('red')])\n",
    "\n",
    "# 创建红蓝混合 colormap\n",
    "rwb = make_colormap([c('red'), c('red'), 0.33, (1,1,1), (1,1,1), 0.66, c('blue')])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x22da0e77708>"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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+NjHPhbPPfdcs8eqy+bNm2P+/PlDPx1q8eLFsWPHjmaPNSY2bdoULS0tsW7dumaPUpfPfe5z0dLSMmyZM2dOs8eq249//OP4xCc+Eeeee25MnDgxLrrooti/f3+zx6rZzJkz3/D30tLSEt3d3c0erWYDAwNxyy23xKxZs2LixIkxe/bsuO222077i1POhHRB/+pXvxrr16+PjRs3xsGDB2PBggVx1VVXxbFjx5o9Ws1OnDgRCxYsiHvuuafZo4zanj17oru7O/bt2xe7du2KX/ziF3HllVfGiRMnmj1azaZNmxabNm2KAwcOxP79++MjH/lIXH311fH973+/2aONSm9vb9x7770xf/78Zo8yKnPnzo1XXnllaHniiSeaPVJdfvazn8WSJUvit37rt2LHjh3xH//xH/EP//APcc455zR7tJr19vYO+zvZtWtXRERcc801TZ6sdnfeeWds3rw5vvCFL8R//ud/xp133hl/+7d/G5///OebPVpEkcxll11WdHd3D70eGBgourq6ip6eniZONXoRUWzbtq3ZY4yZY8eOFRFR7Nmzp9mjjIlzzjmn+NKXvtTsMerW399fvOc97yl27dpVfOhDHyrWrl3b7JHqsnHjxmLBggXNHmNMfOYznyk+8IEPNHuMhli7dm0xe/bsYnBwsNmj1Gz58uXFmjVrhq37oz/6o2LlypVNmuhXUl2hnzx5Mg4cOBBLly4dWjdu3LhYunRpPPXUU02cjP+rr68vIiImTZrU5ElGZ2BgIB555JE4ceJELF68uNnj1K27uzuWL18+7N+ds9ULL7wQXV1dccEFF8TKlSvjyJEjzR6pLt/85jdj4cKFcc0118SUKVPi4osvjvvvv7/ZY43ayZMn46GHHoo1a9Y07DduNtLll18eu3fvjueffz4iIr73ve/FE088EcuWLWvyZE34bWuN9NOf/jQGBgbivPPOG7b+vPPOix/84AdNmor/a3BwMNatWxdLliyJefPmNXucujzzzDOxePHi+N///d945zvfGdu2bYsLL7yw2WPV5ZFHHomDBw9Gb29vs0cZtUWLFsUDDzwQ73vf++KVV16JW2+9NT74wQ/Gs88+Gx0dHc0eryY/+tGPYvPmzbF+/fr4q7/6q+jt7Y2bbrop2traYtWqVc0er27bt2+P119/Pa6//vpmj1KXm2++OSqVSsyZMydaW1tjYGAgbr/99li5cmWzR8sVdM4O3d3d8eyzz561n21GRLzvfe+LQ4cORV9fX3zta1+LVatWxZ49e866qB89ejTWrl0bu3btigkTJjR7nFH79auk+fPnx6JFi2LGjBnx6KOPxg033NDEyWo3ODgYCxcujDvuuCMiIi6++OJ49tln44tf/OJZHfQvf/nLsWzZsujq6mr2KHV59NFH4+GHH46tW7fG3Llz49ChQ7Fu3bro6upq+t9LqqC/+93vjtbW1njttdeGrX/ttdfi/PPPb9JU/Lobb7wxvv3tb8fevXtj2rRpzR6nbm1tbfG7v/u7ERFxySWXRG9vb/zjP/5j3HvvvU2erDYHDhyIY8eOxe///u8PrRsYGIi9e/fGF77whahWq9Ha2trECUfnXe96V7z3ve+Nw4cPN3uUmk2dOvUN/4P4/ve/P/7lX/6lSRON3ksvvRSPPfZYfP3rX2/2KHX7y7/8y7j55pvjT/7kTyIi4qKLLoqXXnopenp6mh70VJ+ht7W1xSWXXBK7d+8eWjc4OBi7d+8+qz/fzKAoirjxxhtj27Zt8W//9m8xa9asZo80pgYHB6NarTZ7jJpdccUV8cwzz8ShQ4eGloULF8bKlSvj0KFDZ3XMIyKOHz8eP/zhD2Pq1KnNHqVmS5YsecNXO59//vmYMWNGkyYavS1btsSUKVNi+fLlzR6lbj//+c9j3Ljh6WxtbY3BwcEmTfQrqa7QIyLWr18fq1atioULF8Zll10Wd999d5w4cSJWr17d7NFqdvz48WFXFi+++GIcOnQoJk2aFNOnT2/iZLXr7u6OrVu3xje+8Y3o6OiIV199NSIiSqVSTJw4scnT1WbDhg2xbNmymD59evT398fWrVvj8ccfj507dzZ7tJp1dHS84TmGd7zjHXHuueeelc83fPrTn44VK1bEjBkz4uWXX46NGzdGa2trXHfddc0erWaf+tSn4vLLL4877rgj/viP/ziefvrpuO++++K+++5r9mh1GRwcjC1btsSqVati/PizNz0rVqyI22+/PaZPnx5z586N7373u3HXXXfFmjVrmj1avq+tFUVRfP7zny+mT59etLW1FZdddlmxb9++Zo9Ul3//938vIuINy6pVq5o9Ws3e7DwiotiyZUuzR6vZmjVrihkzZhRtbW3F5MmTiyuuuKL413/912aPNWbO5q+tXXvttcXUqVOLtra24nd+53eKa6+9tjh8+HCzx6rbt771rWLevHlFe3t7MWfOnOK+++5r9kh127lzZxERxXPPPdfsUUalUqkUa9euLaZPn15MmDChuOCCC4q//uu/LqrVarNHK/w+dABIINVn6ADwdiXoAJCAoANAAoIOAAkIOgAkIOgAkICgA0ACgg4ACQg6ACQg6ACQgKADQAL/D4ujuOUZMA57AAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<Figure size 600x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 创建一个包含40个1的规则向量\n",
    "ruleVector = np.zeros(81)\n",
    "ruleVector[40] = 1\n",
    "\n",
    "# 创建图形窗口\n",
    "fig = figure(0, (6,6))\n",
    "\n",
    "# 绘制规则向量的图像，使用 bw colormap\n",
    "imshow(ruleVector.reshape(9,9), interpolation='none', cmap=bw)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这个规则将具有40位置上的1的示例分类为手指 - 非常酷！\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 现在，让我们测试它的性能！\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 1000x800 with 3 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 可视化匹配结果\n",
    "fig = figure(0, (10, 8))\n",
    "\n",
    "for i in range(3):\n",
    "    # 将图形窗口分为一行三列，并在当前列添加子图\n",
    "    fig.add_subplot(1, 3, i+1)\n",
    "    \n",
    "    # 获取图像字典\n",
    "    imageDict = data[trainingExampleIndices[i]]\n",
    "    \n",
    "    # 从图像字典中提取特征和标签\n",
    "    X1, y1 = extractFeatures(imageDict, whichImage='image1bit', dist=4)\n",
    "    \n",
    "    # 将图像转为灰度\n",
    "    im = makeGrayScale(imageDict)\n",
    "    \n",
    "    # 找到匹配的特征索引\n",
    "    matchingIndices = (X1[:, 40] == 1)\n",
    "    \n",
    "    # 将匹配的特征转为与图像大小相同的布尔数组\n",
    "    matchingImage = matchingIndices.reshape(imageDict['boxHeight'], imageDict['boxWidth'])\n",
    "    \n",
    "    # 在图像上标记匹配位置\n",
    "    im[:,:,0][matchingImage] = 0\n",
    "    im[:,:,1][matchingImage] = 1\n",
    "    im[:,:,2][matchingImage] = 0\n",
    "    \n",
    "    # 显示图像\n",
    "    imshow(im)\n",
    "    axis('off')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这是很多匹配！\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 479   16]\n",
      " [1798 5574]]\n"
     ]
    }
   ],
   "source": [
    "# 找到训练数据中特征40匹配的索引\n",
    "matchingIndices = np.where(trainX[:, 40] == 1)\n",
    "\n",
    "# 创建 yHat 向量，表示规则预测为手指的像素\n",
    "yHat = np.zeros(trainX.shape[0])\n",
    "yHat[matchingIndices] = 1\n",
    "\n",
    "# 计算 False Negatives（FN）、False Positives（FP）、True Positives（TP）和 True Negatives（TN）\n",
    "FN = np.sum(np.logical_and(trainY == 1, yHat == 0))\n",
    "FP = np.sum(np.logical_and(trainY == 0, yHat == 1))\n",
    "TP = np.sum(np.logical_and(trainY == 1, yHat == 1))\n",
    "TN = np.sum(np.logical_and(trainY == 0, yHat == 0))\n",
    "\n",
    "# 创建混淆矩阵\n",
    "confusionMatrix = np.array([[TP, FN], [FP, TN]])\n",
    "\n",
    "# 打印混淆矩阵\n",
    "print(confusionMatrix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.7694165501461803 0.9676767676767677 0.2103645147123408\n"
     ]
    }
   ],
   "source": [
    "# 计算准确率（accuracy）、召回率（recall）和精确度（precision）\n",
    "accuracy = float(TP + TN) / float(trainX.shape[0])\n",
    "recall = float(TP) / (TP + FN)\n",
    "precision = float(TP) / (TP + FP)\n",
    "\n",
    "# 打印准确率、召回率和精确度\n",
    "print(accuracy, recall, precision)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 现在进行测试数据！它能泛化吗！？\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 1000x800 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 可视化测试数据中的匹配结果\n",
    "fig = figure(0, (10, 8))\n",
    "\n",
    "for i in range(2):\n",
    "    # 将图形窗口分为一行两列，并在当前列添加子图\n",
    "    fig.add_subplot(1, 2, i+1)\n",
    "    \n",
    "    # 获取图像字典\n",
    "    imageDict = data[testingExampleIndices[i]]\n",
    "    \n",
    "    # 从图像字典中提取特征和标签\n",
    "    X1, y1 = extractFeatures(imageDict, whichImage='image1bit', dist=4)\n",
    "    \n",
    "    # 将图像转为灰度\n",
    "    im = makeGrayScale(imageDict)\n",
    "    \n",
    "    # 找到匹配的特征索引\n",
    "    matchingIndices = (X1[:, 40] == 1)\n",
    "    \n",
    "    # 将匹配的特征转为与图像大小相同的布尔数组\n",
    "    matchingImage = matchingIndices.reshape(imageDict['boxHeight'], imageDict['boxWidth'])\n",
    "    \n",
    "    # 在图像上标记匹配位置\n",
    "    im[:,:,0][matchingImage] = 0\n",
    "    im[:,:,1][matchingImage] = 1\n",
    "    im[:,:,2][matchingImage] = 0\n",
    "    \n",
    "    # 显示图像\n",
    "    imshow(im, interpolation='none')\n",
    "    axis('off')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 327   14]\n",
      " [ 980 3553]]\n"
     ]
    }
   ],
   "source": [
    "# 找到测试数据中特征40匹配的索引\n",
    "matchingIndices = np.where(testX[:, 40] == 1)\n",
    "\n",
    "# 创建 yHat 向量，表示规则预测为手指的像素\n",
    "yHat = np.zeros(testX.shape[0])\n",
    "yHat[matchingIndices] = 1\n",
    "\n",
    "# 计算 False Negatives（FN）、False Positives（FP）、True Positives（TP）和 True Negatives（TN）\n",
    "FN = np.sum(np.logical_and(testY == 1, yHat == 0))\n",
    "FP = np.sum(np.logical_and(testY == 0, yHat == 1))\n",
    "TP = np.sum(np.logical_and(testY == 1, yHat == 1))\n",
    "TN = np.sum(np.logical_and(testY == 0, yHat == 0))\n",
    "\n",
    "# 创建混淆矩阵\n",
    "confusionMatrix = np.array([[TP, FN], [FP, TN]])\n",
    "\n",
    "# 打印混淆矩阵\n",
    "print(confusionMatrix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.7960607304062371 0.9589442815249267 0.2501912777352716\n"
     ]
    }
   ],
   "source": [
    "# 计算准确率（accuracy）、召回率（recall）和精确度（precision）\n",
    "accuracy = float(TP + TN) / float(testX.shape[0])\n",
    "recall = float(TP) / (TP + FN)\n",
    "precision = float(TP) / (TP + FP)\n",
    "\n",
    "# 打印准确率、召回率和精确度\n",
    "print(accuracy, recall, precision)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "喔呼！我们的方法是泛化的！我们真的做了一个手部检测器，而不是一个手指检测器。但希望这是朝着正确方向迈出的一步。\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true,
    "jupyter": {
     "outputs_hidden": true
    }
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "depth-camera",
   "language": "python",
   "name": "depth-camera"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.16"
  },
  "latex_envs": {
   "bibliofile": "biblio.bib",
   "cite_by": "apalike",
   "current_citInitial": 1,
   "eqLabelWithNumbers": true,
   "eqNumInitial": 0
  },
  "toc": {
   "toc_cell": false,
   "toc_number_sections": false,
   "toc_threshold": 6,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
